﻿using UnityEngine;
using System.Collections;


[RequireComponent(typeof(SpriteRenderer), typeof(Rigidbody2D), typeof(Animator))]
public class SoyBoyController : MonoBehaviour {

	public float speed = 14;
	public float accel = 6;
	public float airAccel = 3;
	public bool isJumping;
	public float jumpSpeed = 8;
	public float jumpDurationThreshold = 0.25f;
	public float jump = 14;

	private Vector2 input;
	private SpriteRenderer sr;
	private Rigidbody2D rb;
	private Animator animator;
	private float rayCastLengthCheck = 0.005f;
	private float width;
	private float height;
	private float jumpDuration;


	// Called before Start(), after prefab instance
	void Awake() {
		sr = GetComponent<SpriteRenderer> ();
		rb = GetComponent<Rigidbody2D> ();
		animator = GetComponent<Animator> ();
		width = GetComponent<Collider2D> ().bounds.extents.x + 0.1f;
		height = GetComponent<Collider2D> ().bounds.extents.y + 0.2f;
	}

	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		input.x = Input.GetAxis ("Horizontal");
		input.y = Input.GetAxis ("Jump");

		if (input.x > 0.0f) {
			sr.flipX = false;
		} else if (input.x < 0.0f) {
			sr.flipX = true;
		}

		//jump
		if (input.y >= 1f) {
			jumpDuration += Time.deltaTime;
		} else {
			isJumping = false;
			jumpDuration = 0.0f;
		}

		if (IsPlayerOnGround() && isJumping == false) {
			if (input.y > 0) {
				isJumping = true;
			}
		}

		if (jumpDuration > jumpDurationThreshold) input.y = 0;
	}

	void FixedUpdate() {
		var acceleration = 0f;
		if (IsPlayerOnGround()) {
			acceleration = accel;
		} else {
			acceleration = airAccel;
		}

		var xVelocity = 0f;
		if (IsPlayerOnGround() && input.x == 0) {
			xVelocity = 0;
		} else {
			xVelocity = rb.velocity.x;
		}

		var yVelocity = 0f;
		if (IsPlayerTouchingGroundOrWall() && input.y >= 1) {
			yVelocity = jump;
		} else {
			yVelocity = rb.velocity.y;
		}

		rb.AddForce(new Vector2(((input.x * speed) - rb.velocity.x) * acceleration, 0));
		rb.velocity = new Vector2 (xVelocity, yVelocity);

		if (isJumping && jumpDuration < jumpDurationThreshold) {
			rb.velocity = new Vector2(rb.velocity.x, jumpSpeed);
		}
	}

	public bool IsPlayerOnGround() {
		//1
		bool groundCheck1 = Physics2D.Raycast (new Vector2 (transform.position.x, transform.position.y - height),
		 -Vector2.up, rayCastLengthCheck);

		bool groundCheck2 = Physics2D.Raycast (new Vector2 (transform.position.x + (width - 0.2f), transform.position.y - height), 
		-Vector2.up, rayCastLengthCheck);

		bool groundCheck3 = Physics2D.Raycast (new Vector2 (transform.position.x - (width - 0.2f), transform.position.y - height), 
		-Vector2.up, rayCastLengthCheck);

		return groundCheck1 || groundCheck2 || groundCheck3;
	}

	public bool IsWallToLeftOrRight() {
		bool wallOnLeft = Physics2D.Raycast (new Vector2 (transform.position.x - width, transform.position.y), 
		Vector2.left, rayCastLengthCheck);

		bool wallOnRight = Physics2D.Raycast (new Vector2 (transform.position.x + width, transform.position.y), 
		Vector2.right, rayCastLengthCheck);

		return wallOnLeft || wallOnRight;
	}

	public bool IsPlayerTouchingGroundOrWall() {
		return IsPlayerOnGround () || IsWallToLeftOrRight ();
	}
}
